home *** CD-ROM | disk | FTP | other *** search
- /*
- READEL.C
- by Paul S. Hirose, 1990 Nov 12
- Handles orbital element files and reads the elements.
-
- This file is in the public domain.
-
- 400 - 499
-
- library functions, typedefs, and #defines used in this file:
-
- atof atoi cos EOF fclose FILE fopen free fseek ftell getc isdigit
- isspace NULL printf strcmp strcpy
- */
-
- #include "b:seesat.h" /* global header */
-
- extern void free(), printf();
- extern char *strcpy();
- extern int atoi(), fclose(), getc(), isdigit(), isspace(), strcmp();
- extern long int fseek(), ftell();
- extern double atof(), cos();
- extern FILE *fopen();
-
- /* Number of lines on your terminal. Only affects the listing of satellite
- names. You will get LINES-1 rows of names, followed by "more>" on a separate
- line. The cursor will be positioned to the right of '>'. */
- #define LINES 24
-
- /* Maximum number of chars to accept from satellite name field in file. May
- be from 1 to 22. */
- #define LNAME 22
-
- #define BSIZE 50 /* # of index entries in a storage block */
-
- #define NSTAT 0 /* normally 0. Non-zero makes static functions
- and data extern, for testing */
-
- #if NSTAT
- /* define & declare all functions in this file as extern */
- #define STATIC
- #define SC extern
-
- #else
- #define STATIC static
- #define SC static
- #endif
-
- /*############################ LOCAL DATA ############################*/
-
- STATIC FILE *fp = NULL; /* orbital element file */
-
- struct node { /* hash node for index of satellites */
- char name[LNAME+1]; /* satellite name */
- long int offset; /* location of element set in file */
- struct node *link; /* point to next struct in chain */
- };
-
- STATIC struct node *heads[8]; /* hash table */
-
- struct bloc { /* space for BSIZE index entries */
- struct node nodes[BSIZE];
- struct bloc *next; /* link to next block */
- };
-
- STATIC struct bloc *first; /* ptr to first block */
-
- STATIC unsigned sets; /* number of element sets in file */
-
- /*######################## LOCAL FUNCTIONS ########################*/
-
- SC double angle(); /* convert string to angle in radians */
- SC int csum(); /* checksums a line of data */
- SC double epjd(); /* converts NORAD Epoch string to epoch */
- SC int getel(); /* transfers elements from file to variables */
- SC int getlin(); /* move a line from file to buffer */
- SC unsigned hash(); /* turns string into value from 0 to 7 */
- SC void nullsp(); /* replace spaces in buffer with nulls */
- SC double sci(); /* returns value of scientific notation #'s */
- SC char *sknull(); /* skip leading nulls */
-
- /*############################## CODE ##############################*/
-
- STATIC double
- angle(string)
- char *string;
- /* Returns the radian value of the angle (degrees) in "string".
- Leading nulls on "string" will be skipped, so it had better contain
- at least one digit. */
- {
- return atof(sknull(string)) * de2ra;
- }
-
-
- STATIC int
- csum(line)
- char *line;
- /* Does a checksum modulo 10 on the given line. Digits = their
- value, '-' = 1, '+' = 2, all other chars = 0. Returns 0 if ok. */
- {
- char c;
- int i = 0; /* checksum accumulator */
- int count = 69; /* length of data line */
-
- /* accumulate checksum from all but the last char in the line,
- which is the desired checksum */
-
- while (--count) {
- if (isdigit(c = *line++))
- i += c - '0';
- else if (c == '-')
- ++i;
- else if (c == '+')
- i += 2;
- /* all other chars = 0 */
- }
-
- /* Convert accumulated # to mod 10, subtract desired sum */
- return i % 10 - (*line - '0');
- }
-
-
- STATIC double
- epjd(buf)
- char *buf;
- /* Given pointer to the orbital elements Epoch field, returns Julian Date
- (unit = minutes). Positions for Days tens and hundreds and Years tens digits
- must contain either a digit or '\0'. Format of Epoch field: YYDDD.dddddddd
- */
- {
- double day;
- int year;
-
- day = atof(sknull(buf + 2));
-
- buf[2] = '\0'; /* day 100s digit = null */
- year = atoi(sknull(buf));
- year += (year < 57) ? 1999 : 1899;
-
- /* Subtract .5 because julday() returns JD at 12h on given day */
- return (julday(year, 11, 31) + day - .5) * xmnpda;
- }
-
-
- STATIC int
- getel()
- /* Sets the global orbital element variables and name[] (satellite name)
- using data from the currently open element file. Initializes precession.
- Sets global iflag to 1. The position in the file must be at the satellite
- name or in white space preceding the name. Returns -1 if incorrect format in
- file, 0 if near-earth object, 1 if deep space. Prints warning if checksum
- error in file, but will still attempt to use elements. */
- {
- double ao, a1, delo, del1, temp;
- int check;
- char line1[70], line2[70];
-
- getlin(name, LNAME+1);
-
- /* Get first data line from file. Verify that it's 69 chars long &
- begins with '1' */
-
- if (getlin(line1, 70) != 69 || *line1 != '1')
- return -1; /* incorrect format */
- check = csum(line1); /* Line 1 checksum */
-
- /* get second data line */
- if (getlin(line2, 70) != 69 || *line2 != '2')
- return -1; /* incorrect format */
- check += csum(line2); /* add Line 2 checksum */
-
- /* print both lines at console */
- printf("%s\n%s\n", line1, line2);
- if (check)
- printf("CAUTION: FAILED CHECKSUM\n");
-
- /* replace spaces with nulls */
- nullsp(line1);
- nullsp(line2);
-
- xmo = angle(line2 + 43);
- xnodeo = angle(line2 + 17);
- omegao = angle(line2 + 34);
- xincl = angle(line2 + 8);
- FTEST((400, 4, 3, &xmo, &xnodeo, &omegao, &xincl));
-
- /* put a decimal point in front of eccentricity, decode it */
- line2[25] = '.';
- eo = atof(line2 + 25);
-
- temp = twopi / (xmnpda * xmnpda);
-
- /* Make sure mean motion is null-terminated, since rev. no.
- may immediately follow. */
- line2[63] = '\0';
- xno = atof(sknull(line2 + 52)) * temp * xmnpda;
- if (line1[35]) /* field isn't blank */
- xndt2o = atof(sknull(line1 + 33)) * temp;
- else
- xndt2o = 0.;
- xndd6o = sci(line1 + 44) * temp / xmnpda;
-
- bstar = sci(line1 + 53);
- epoch = epjd(line1 + 18);
- ETEST((402, 5, 3, &eo, &xno, &xndt2o, &xndd6o, &bstar));
- FTEST((403, 1, 3, &epoch));
-
- toffs = 0.; /* reset OFFSET */
- iflag = 1;
-
- #if ENPRE /* precession code enabled */
- /* initialize direction cosines to precess R.A./dec. */
- inpre();
- #endif
-
- /* Compute period. Object is deep space if <= 6.4 revs/day */
- a1 = POW(xke / xno, tothrd);
- temp = cos(xincl);
- temp = 1.5 * ck2 * (3. * temp * temp - 1.) /
- POW(1. - eo * eo, 1.5);
- del1 = temp / (a1 * a1);
- ao = a1 * (1. - del1 * (.5 * tothrd + del1 *
- (1. + 134. / 81. * del1)));
- delo = temp / (ao * ao);
-
- if (xno / (1. + delo) <= .0279253)
- return 1; /* deep space */
- else
- return 0; /* near earth */
- }
-
-
- STATIC int
- getlin(dest, size)
- int size; /* must be at least 2 */
- char *dest;
- /* Copy a line from the currently open file into dest[]. "Size" is length of
- dest[], and must be at least 2. Any leading white space is skipped. String
- copied to dest[] will be null terminated.
- Exit occurs when: 1) size - 1 chars have been copied, or 2) '\n'
- detected (the '\n' won't be sent to dest[]), or 3) EOF detected. In case 1
- or 2, the next read from the file is guaranteed to start at beginning of the
- next line. Returns # of chars copied to dest[] (final null not counted). */
- {
- int c, i;
-
- i = size - 1; /* i = # of chars desired */
-
- /* go past leading white space */
- while (isspace(c = getc(fp)))
- ;
-
- /* Move chars to buffer till we we reach end of line, or
- have gotten # requested, or end of file. */
-
- do {
- if (c == EOF)
- break;
- *dest++ = c;
- } while (--i && (c = getc(fp)) != '\n');
- *dest = '\0';
-
- /* At this point, i is how many chars we've fallen short */
-
- if (!i) /* requested # of chars were found */
- while ((c = getc(fp)) != '\n' && c != EOF)
- ; /* position at start of next line */
-
- return size - 1 - i; /* how many copied */
- }
-
-
- STATIC unsigned
- hash(string)
- char *string;
- /* Add all chars in string, returns sum modulo 8 */
- {
- unsigned sum;
- char c;
-
- for (sum = 0; c = *string++; )
- sum += c;
- return sum & 7;
- }
-
-
- void
- hfree() /* frees the index space */
- {
- struct bloc *blocp;
-
- for (blocp = first; blocp; blocp = blocp->next)
- free((VOIDP) blocp);
- first = NULL;
- }
-
-
- void
- index()
- /* List all satellites in the index generated by opn(). */
- {
- unsigned total, u, line, column;
- struct bloc *blocp;
- struct node *nodep;
-
- ++tokp; /* point to next command */
-
- total = sets; /* total no. of element sets in file */
- line = LINES - 1;
- column = 3;
-
- for (blocp = first; blocp; blocp = blocp->next) {
- nodep = blocp->nodes;
- for (u = BSIZE; u--; ) {
- if (line == 0) { /* screen is full */
- printf("more");
- tok(); /* cmd line prompt */
- if (*tokp) /* cmd was typed */
- return;
- else /* only a CR was typed */
- line = LINES - 1;
- }
- if (--column)
- printf("%-25s", nodep->name);
- else { /* rightmost column */
- printf("%s\n", nodep->name);
- column = 3;
- --line;
- }
- ++nodep;
- if (--total == 0)
- break;
- } }
- if (column != 3)
- printf("\n");
- }
-
-
- void
- load()
- /* Takes the next argument on the command line as the name of the satellite
- to load from the currently open file. */
- {
- struct node *nodep;
-
- ++tokp; /* point to name */
-
- /* search hash table for a matching name */
- for (nodep = heads[hash(*tokp)]; nodep; nodep = nodep->link)
- if (strcmp(nodep->name, *tokp) == 0)
- break; /* found matching name */
-
- if (nodep) {
- /* found matching name */
- fseek(fp, nodep->offset, 0);
-
- /* get elements, report status */
- switch (getel()) {
- case -1:
- printf("ABORTED LOAD: INCORRECT FORMAT\n");
- break;
- case 0:
- printf("satellite loaded\n");
- break;
- case 1:
- printf("CAUTION: DEEP SPACE SATELLITE\n");
- }
- } else
- printf("NO SUCH SATELLITE\n");
- ++tokp; /* point to next command */
- }
-
-
- STATIC void
- nullsp(buf)
- char *buf;
- /* replaces each occurrence of ' ' in string "buf" with a null */
- {
- char c;
-
- while (c = *buf) {
- if (c == ' ')
- *buf = '\0';
- ++buf;
- } }
-
-
- void
- opn()
- /* Take the next argument on the command line as the name of the orbital
- element file to open. Builds the index used by index() and load(). If an
- elements file is already open, it will be closed and the associated index
- deleted before opening the new file. External "fp" is set to the returned
- value from fopen(). */
- {
- struct bloc *blocp, *last;
-
- FILE *tfp;
- long int fpos; /* position in file */
- unsigned int n50, hshval;
- char *cp, buffer[70];
- struct node *indexp, *nodep;
-
- tokp += 2; /* point to next command */
-
- if ((tfp = fopen(*(tokp - 1), "r")) == NULL) {
- printf("CAN'T OPEN %s\n", *(tokp - 1));
- return;
- }
-
- if (fp) { /* close old file, delete its index */
- struct node **nodepp;
- unsigned u;
-
- fclose(fp);
- hfree(); /* release index space */
- nodepp = heads;
- for (u = 8; u--; )
- *nodepp++ = NULL; /* clear hash table */
- }
-
- fp = tfp;
- sets = 0; /* counts # of element sets processed */
- n50 = 0; /* storage remaining */
- fpos = 0L; /* position in file */
-
- while (getlin(buffer, LNAME+1) != 0) {
- /* got a satellite name; add it to index */
- if (n50 == 0) { /* need more storage */
- blocp = MALLOC(sizeof (struct bloc));
- if (blocp) {
- if (first == NULL) /* first block */
- first = blocp;
- else
- last->next = blocp;
- last = blocp;
- blocp->next = NULL; /* end of chain */
- indexp = blocp->nodes;
- n50 = BSIZE; /* reset storage counter */
- } else {
- printf("MEMORY FULL: %u INDEXED\n", sets);
- return;
- } }
- /* add the element set to the index */
-
- /* eliminate any trailing spaces on name */
- for (cp = buffer; *++cp; )
- ; /* find end of name string */
- while (isspace(*--cp))
- ; /* point to last non-white char */
- cp[1] = '\0';
-
- strcpy(indexp->name, stoup(buffer));
- indexp->offset = fpos; /* location in file */
- indexp->link = NULL; /* end of chain mark */
-
- /* link it to the hash table */
- hshval = hash(buffer); /* hash satellite name */
- if (nodep = heads[hshval]) {
- /* hash table entry is already taken */
- while (nodep->link)
- nodep = nodep->link; /* find end of chain */
- nodep->link = indexp; /* attach new entry */
- } else
- heads[hshval] = indexp;
-
- getlin(buffer, 70); /* move past Line 1 */
- getlin(buffer, 70); /* move past Line 2 */
- ++sets; /* # of satellites found */
- --n50; /* space remaining in index */
- ++indexp; /* point to next free place in index */
- fpos = ftell(fp); /* update file position */
- }
- printf("complete; %u satellites found\n", sets);
- }
-
-
- STATIC double
- sci(string)
- char *string;
- /* Converts quasi scientific notation to double. Format: SnSn where S is
- either '-' or '\0' and n represents a sequence of 1 or more digits. An
- implied decimal point exists to the left of the left n. Total length 27
- chars max. */
- {
- char buf[30], *bufptr;
-
- bufptr = buf;
-
- if (string[1] == '\0')
- return 0.;
-
- /* get significand */
- if (*string == '-')
- *bufptr++ = '-';
- *bufptr = '.';
- while (isdigit(*++bufptr = *++string))
- ; /* copy significand */
- *bufptr++ = 'E';
-
- /* get exponent */
- if (*string == '\0') /* no sign on exponent */
- ++string;
-
- strcpy(bufptr, string); /* copy exponent */
- return atof(buf);
- }
-
-
- STATIC char *
- sknull(cptr)
- char *cptr;
- /* Skip nulls. Returns pointer to first non-null char in "cptr". */
- {
- while (!*cptr)
- ++cptr;
-
- return cptr;
- }
- ndexp; /* point to next free place in index */
-